package com.nickstumpos.android.easyVolume.playRinger.streams;

import android.content.Context;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;

import com.nickstumpos.android.easyVolume.playRinger.IPlaySample;
import com.nickstumpos.android.easyVolume.streams.types.Stream;

public class MediaPlaySample implements IPlaySample {

	private class Worker implements Runnable {

		private final Object	lock	= new Object();
		private Looper				looper;

		Worker(String name) {
			Thread t = new Thread(null, this, name);
			t.start();
			synchronized (this.lock) {
				while (this.looper == null) {
					try {
						this.lock.wait();
					} catch (InterruptedException ex) {
					}
				}
			}
		}

		public Looper getLooper() {
			return this.looper;
		}

		public void quit() {
			this.looper.quit();
		}

		public void run() {
			synchronized (this.lock) {
				Looper.prepare();
				this.looper = Looper.myLooper();
				this.lock.notifyAll();
			}
			Looper.loop();
		}
	}

	private static final int	PLAY_ONCE					= 1;

	private static final int	STOP							= 3;
	Uri												customRingtoneUri	= RingtoneManager
																									.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
	Ringtone									mediaPlayer;
	Context										context;
	private Worker						mediaThread;
	private Handler						mediaHandler;
	private boolean						mediaPending;
	private long							firstEventTime		= -1;
	private long							firstStartTime		= -1;
	private static final int	PAUSE_LENGTH			= 1000;																						// ms

	private Stream						stream;

	public MediaPlaySample(Context main, Stream stream) {
		this.context = main;
		this.stream = stream;
	}

	private boolean isPlaying() {
		synchronized (this) {
			return this.mediaPlayer != null && this.mediaPlayer.isPlaying()
					|| this.mediaHandler != null
					&& this.mediaHandler.hasMessages(MediaPlaySample.PLAY_ONCE);
		}
	}

	private void makeLooper() {
		if (this.mediaThread == null) {
			this.mediaThread = new Worker("player");
			this.mediaHandler = new Handler(this.mediaThread.getLooper()) {

				@Override
				public void handleMessage(Message msg) {
					Ringtone mp = null;
					switch (msg.what) {
						case PLAY_ONCE:
							if (MediaPlaySample.this.mediaPlayer == null
									&& !this.hasMessages(MediaPlaySample.STOP)) {
								mp = RingtoneManager.getRingtone(MediaPlaySample.this.context,
										MediaPlaySample.this.customRingtoneUri);
								mp.setStreamType(MediaPlaySample.this.stream
										.getAndroidConstant());
								synchronized (MediaPlaySample.this) {
									if (!this.hasMessages(MediaPlaySample.STOP)) {
										MediaPlaySample.this.mediaPlayer = mp;
									}
								}
							}
							mp = MediaPlaySample.this.mediaPlayer;
							while (mp != null && !this.hasMessages(MediaPlaySample.STOP)) {
								if (!mp.isPlaying()) {
									mp.play();
								}
								synchronized (MediaPlaySample.this) {
									MediaPlaySample.this.mediaPending = false;
									if (MediaPlaySample.this.firstStartTime < 0) {
										MediaPlaySample.this.firstStartTime = SystemClock
												.elapsedRealtime();
									}
								}
								try {
									Thread.sleep(MediaPlaySample.PAUSE_LENGTH);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
							break;
						case STOP:
							mp = (Ringtone) msg.obj;
							if (mp != null) {
								mp.stop();
							}
							this.getLooper().quit();
							break;
					}
				}
			};
		}
	}

	@Override
	public void start() {

		synchronized (this) {

			if (!this.isPlaying() && !this.mediaPending) {
				this.makeLooper();
				this.mediaHandler.removeCallbacksAndMessages(null);
				this.mediaPending = true;
				if (this.firstEventTime < 0) {
					this.firstEventTime = SystemClock.elapsedRealtime();
					this.mediaHandler.sendEmptyMessage(MediaPlaySample.PLAY_ONCE);
				} else {
					if (this.firstStartTime > 0) {
						this.mediaHandler.sendEmptyMessageDelayed(
								MediaPlaySample.PLAY_ONCE, this.firstStartTime
										- this.firstEventTime);
					} else {
						this.firstEventTime = SystemClock.elapsedRealtime();
					}
				}
			}
		}

	}

	@Override
	public void stop() {
		synchronized (this) {
			if (this.mediaHandler != null) {
				this.mediaHandler.removeCallbacksAndMessages(null);
				Message msg = this.mediaHandler.obtainMessage(MediaPlaySample.STOP);
				msg.obj = this.mediaPlayer;
				this.mediaHandler.sendMessage(msg);
				this.mediaThread = null;
				this.mediaHandler = null;
				this.mediaPlayer = null;
				this.firstEventTime = -1;
				this.firstStartTime = -1;
				this.mediaPending = false;
			}
		}

	}

}
